package mammuthus.controller.app

import net.csdn.annotation.rest.{State, BasicInfo, At}
import net.csdn.modules.http.{ApplicationController, ViewType, RestRequest}
import net.liftweb.{json => SJSon}
import mammuthus.tool.{TemplateTool, Constants}
import com.google.inject.Inject
import mammuthus.master.Master
import net.csdn.common.env.Environment
import scala.collection.JavaConversions._

import mammuthus.controller.filter.{TokenAuthFilter, AppNameCheckFilter}
import scala.io.Source
import mammuthus.slave.InteractiveShellCommand

/**
 * 6/9/15 WilliamZhu(allwefantasy@gmail.com)
 */
class AppStatusTaskController @Inject()(akkaMaster: Master, env: Environment) extends ApplicationController with TokenAuthFilter with AppNameCheckFilter {

  implicit val formats = SJSon.Serialization.formats(SJSon.NoTypeHints)

  val appRootDir = Constants.getAppRootDir

  def appName = param("appName")

  @At(path = Array("/app/list"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "获取应用列表以及那些节点部署情况",
    state = State.alpha,
    testParams = "",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def appList = {
    auth
    val res = akkaMaster.appMap.values.toList

    render(SJSon.Serialization.write(res), ViewType.json)

  }

  @At(path = Array("/app/info"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "获取应用列表以及那些节点部署情况",
    state = State.alpha,
    testParams = "",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def appInfo = {
    auth
    checkAppName
    render(SJSon.Serialization.write(akkaMaster.findApp(param("appName"))), ViewType.json)
  }

  @At(path = Array("/app/put/extra"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "为应用写入一些额外信息",
    state = State.alpha,
    testParams = "?appName=zookeeper",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def appPutExtra = {
    auth()

    if (isEmpty(param("appName"))) render(400, s"appName required ")

    render(SJSon.Serialization.write(akkaMaster.appPutExtra(params().toMap)), ViewType.json)
  }

  @At(path = Array("/app/get/extra"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "为应用写入一些额外信息",
    state = State.alpha,
    testParams = "?appName=zookeeper&name=",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def appGetExtra = {
    auth()
    if (isEmpty(param("appName")) && isEmpty(param("app"))) render(400, s"appName or app required ")
    import scala.collection.JavaConversions._
    val p = params().toMap
    render(SJSon.Serialization.write(akkaMaster.appGetExtra(p)), ViewType.json)
  }


  @At(path = Array("/app/control"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "对安装的应用进行 启动，停止，重启，询问状态等动作",
    state = State.alpha,
    testParams = "",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def appControl = {

    auth

    checkAppName

    if (isEmpty(param("command"))) render(400, "command is required start|status|stop|restart")
    val appName = param("appName")
    val command = param("command")
    val appList = akkaMaster.appList

    if (param("appType") != "default" && !appList.contains(param("appName"))) render(400, s"${param("appName")} 不存在")

    val shell = if (param("appType") == "default") {

      if (hasParam("moduleFile") && !param("moduleFile").isEmpty) {

        akkaMaster.writeFile(param("slaves"),
          Source.fromFile(env.templateDirFile().getPath + "/command/shell/app.sh").getLines.mkString("\n"), s"${appRootDir}$appName/app.sh", false)

        TemplateTool.render("/template/command/shell/app_sh/appWithModule.vm", Map(
          "app" -> s"${appRootDir}$appName",
          "moduleFile" -> param("moduleFile"),
          "command" -> command
        ))

      } else {
        TemplateTool.render("/template/command/shell/app_sh/app.vm", Map(
          "app" -> s"${appRootDir}$appName",
          "command" -> command
        ))
      }

    } else
      s"${appRootDir}$appName/control.sh $command"


    val list = appList

    logger.info("shell " + shell)
    val res = if (paramAsBoolean("block", false) == true)
      akkaMaster.executeBlockShellCommand(param("slaves", if (appList.contains(appName)) list(appName).mkString(",") else ""), shell)
    else
      akkaMaster.executeShellCommand(param("slaves", if (appList.contains(appName)) list(appName).mkString(",") else ""), shell, paramAsLong("tt", InteractiveShellCommand.defaultTimeOut))

    render(SJSon.Serialization.write(res), ViewType.json)

  }


  @At(path = Array("/conf/control"), types = Array(RestRequest.Method.GET, RestRequest.Method.POST))
  @BasicInfo(
    desc = "激活mammuthus-conf系统",
    state = State.alpha,
    testParams = "",
    testResult = "",
    author = "WilliamZhu",
    email = "allwefantasy@gmail.com"
  )
  def mammuthusConfControl = {
    auth
    val res = akkaMaster.startMammuthusConf(param("slaves", akkaMaster.slaves.keys.mkString(",")))
    render(SJSon.Serialization.write(res), ViewType.json)

  }

}
